/**
 *Copyright 2013 by dragon.
 *
 *File name: Peer.java
 *Author:      dragon
 *Email:       fufulove2012@gmail.com
 *Blog:        http://blog.csdn.net/xidomlove
 *Version:     1.0.0
 *Date:        2013-10-8 下午1:47:49
 *Description: 
 */
package com.dragon.jaxel.bittorrent;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.concurrent.LinkedBlockingQueue;

import com.dragon.log.Logger;

/**
 * @author dragon8
 * 
 */
public class Peer implements Comparable<Peer> {

	/**
	 * 网络连接
	 */
	SocketChannel socketChannel;

	InetSocketAddress address;

	/**
	 * @return the address
	 */
	InetSocketAddress getAddress() {
		return address;
	}

	/**
	 * 读取的数据缓冲区
	 */
	ByteBuffer peerMessageBuffer = ByteBuffer.allocateDirect(1024 * 32);

	/**
	 * 该peer的piece位图
	 */
	BitSet bitSet;

	/**
	 * 是否是被动连接
	 */
	boolean isPassive = false;

	boolean isHandshakeRecieved = false;
	boolean isBitfieldRecieved = false;

	boolean amChoking = true;
	boolean amInterested = false;
	boolean peerChoking = true;
	boolean peerInterested = false;

	boolean isRequestingPiece = false;
	/**
	 * 待发送消息队列
	 */
	LinkedBlockingQueue<ByteBuffer> sendQueue = new LinkedBlockingQueue<ByteBuffer>();

	/**
	 * 该peer的优先级，越小则优先级越高
	 */
	private int priority = 0;

	/**
	 * 增加优先级
	 */
	void increasePriority() {
		priority -= 1;
	}

	/**
	 * 减少优先级
	 */
	void decreasePriority() {
		priority += 1;
	}

	/**
	 * 创建一个peer对象，表示bit torrent协议中的一个端
	 * 
	 * @param ip
	 * @param port
	 */
	Peer(InetSocketAddress address) {
		super();
		this.address = address;
		// peerMessageBuffer.order(ByteOrder.LITTLE_ENDIAN);
	}

	@Override
	public int compareTo(Peer o) {
		// TODO Auto-generated method stub
		return this.priority - o.priority;
	}

	/**
	 * 连接到该peer
	 * 
	 * @throws IOException
	 */
	void connect() throws IOException {
		socketChannel = SocketChannel.open();
		socketChannel.configureBlocking(false);
		socketChannel.connect(address);
	}

	/**
	 * 注册socket事件
	 * 
	 * @param selector
	 * @throws ClosedChannelException
	 */
	void registerEvent(Selector selector) throws ClosedChannelException {
		socketChannel.register(selector, SelectionKey.OP_READ
				| SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE, this);
	}

	/**
	 * 关闭连接
	 * 
	 * @throws IOException
	 */
	void close() {
		if (socketChannel != null) {
			try {
				socketChannel.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				Logger.getDefaultLogger().debug(e.getMessage());
			}
		}
		socketChannel = null;
	}

	/**
	 * 是否已经连接
	 * 
	 * @return
	 */
	boolean isConnected() {
		if (socketChannel == null) {
			return false;
		}
		return socketChannel.isConnected();
	}

	boolean sendMessage(ByteBuffer buffer) {
		try {
			sendQueue.put(buffer);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			return false;
		}
		return true;
	}

	boolean sendPendingMessage() {
		if (sendQueue.isEmpty()) {

		} else {
			try {
				socketChannel.write(sendQueue.poll());
				return true;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				Logger.getDefaultLogger().debug(e.getMessage());
			}
		}
		return false;
	}
}
